package com.lagou.tomcat.parser;

import com.lagou.tomcat.container.*;
import com.lagou.tomcat.mapper.MappedContext;
import com.lagou.tomcat.mapper.MappedHost;
import com.lagou.tomcat.mapper.Mapper;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhangjinshan
 * @version 1.0
 * @description server.xml解析
 * @date 2021/7/15 上午8:04
 */

public class ServerXmlParser {

    private InputStream inputStream;

    public ServerXmlParser(InputStream inputStream) {
        this.inputStream = inputStream;
    }

    public void parse(List<Service> services){
        SAXReader reader = new SAXReader();
        Document document = null;
        try {
            document = reader.read(inputStream);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        Element root = document.getRootElement();
        List<Element> serviceElements = root.selectNodes("Service");
        for (Element serviceElement : serviceElements) {
            Service service = new Service();
            //解析connector
            List<Element> connectorElements = serviceElement.selectNodes("Connector");
            List<Connector> connectors = new ArrayList<>();
            for (Element connectorElement : connectorElements) {
                int port = Integer.parseInt(connectorElement.attributeValue("port"));
                Connector connector = new Connector(port);
                connectors.add(connector);
            }
            service.setConnectors(connectors);
            //解析engine
            Node engineElement = serviceElement.selectSingleNode("Engine");
            Engine engine = new Engine();
            /***封装mapper-start***/
            Mapper mapper = new Mapper();
            //解析host
            List<Element> hostElements = engineElement.selectNodes("Host");
            Map<String, MappedHost> hosts = new HashMap<>();
            for (Element hostElement : hostElements) {
                // 获取appBase属性并验证路径是否正确
                String appBase = hostElement.attributeValue("appBase");
                File appBaseDir = new File(appBase);
                if (!appBaseDir.exists() || !appBaseDir.isDirectory()) {
                    throw new RuntimeException("FileDir not found :" + appBase);
                }
                String hostName = hostElement.attributeValue("name");
                Host host = new Host(hostName, appBase);
                Map<String, MappedContext> contexts = new HashMap<>();
                for (File contextFile : appBaseDir.listFiles()) {
                    if (contextFile.isFile()) {
                        continue;
                    }
                    String contextPath = "/" + contextFile.getName();
                    String absolutePath = contextFile.getAbsolutePath().replaceAll("\\\\", "/");
                    Context context = new Context(contextPath, absolutePath);
                    MappedContext mappedContext = new MappedContext(context);
                    //读取web.xml
                    File webXml = new File(contextFile.getAbsolutePath() + "/web.xml");
                    try {
                        WebXmlParser webXmlParser = new WebXmlParser(new FileInputStream(webXml), mappedContext);
                        webXmlParser.parse();
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                    contexts.put(contextPath, mappedContext);
                }
                MappedHost mappedHost = new MappedHost(contexts, host);
                hosts.put(hostName, mappedHost);
            }
            /***封装mapper-end***/
            mapper.setHosts(hosts);
            engine.setMapper(mapper);
            service.setEngine(engine);
            services.add(service);
        }
    }
}
